#include "action.h"

namespace IAlib
{

Action::Action()
{
    m_Name = "";
    m_exec_time = 0;
    m_exec_time_max = 0;
    m_exec_time_min = 0;
    m_type=0;
    m_state = 0;
	m_exclusive = true;
	m_execution_type = Action::ExeType_OneShot;
    m_mandatory = true;
    m_attempts_number = -1;
}
//-----------------------------------------------------------
Action::Action( const QString& Name )
{
    m_Name = Name;
    m_exec_time = 0;
    m_exec_time_max = 0;
    m_exec_time_min = 0;
    m_type = 0;
    m_state = 0;
	m_exclusive = true;
	m_execution_type = Action::ExeType_OneShot;
    m_mandatory = true;
    m_attempts_number = -1;
}
//------------------------------------------------------------
Action::Action ( const Action & a )
{
    m_Name = a.m_Name;
    m_Precondition = a.m_Precondition;
    m_Effect = a.m_Effect;
    m_exec_time = a.m_exec_time;
    m_exec_time_max = a.m_exec_time_max;
    m_exec_time_min = a.m_exec_time_min;
    m_type = a.m_type;
    m_ID_actor_origin = a.m_ID_actor_origin;
    m_ID_actor_target = a.m_ID_actor_target;
    m_message = a.m_message;
    m_state = a.getState();
    m_dialog_id = a.m_dialog_id;
	m_exclusive = a.m_exclusive;
	m_execution_type = a.m_execution_type;
    m_artefacts_class = a.m_artefacts_class;
    m_exec_time_max = a.m_exec_time_max;
    m_exec_time_min = a.m_exec_time_min;
    m_mandatory = a.m_mandatory;
    m_attempts_number = a.m_attempts_number;
}

//-------------------------------------------------------------
Action::~Action()
{

}

////////////////////////////////////////////////////////////////////////////////////////////

void Action::addPrecondition( const Fact&  prec )
{
    m_Precondition.insert(m_Precondition.size(), prec);
}

/////////////////////////////////////////////////////////////////////////////////////////////////

void Action::addEffect( const Fact&  effect)
{
    m_Effect.insert(m_Effect.size(), effect);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

void Action::addArtefactClass(const QString &artefact_class)
{
    m_artefacts_class.append(artefact_class);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

void Action::removePrec( const QString& FactName )
{
    int i = 0;
    while ( i < m_Precondition.size() )
    {
        if ( m_Precondition[i].getFactName() == FactName )
        {
            m_Precondition.removeAt(i);
            break;
        }
        i++;
    }
}

void Action::removeEffect( const QString& FactName )
{
    int i = 0;
    while ( i < m_Effect.size() )
    {
        if ( m_Effect[i].getFactName() == FactName )
        {
            m_Effect.removeAt(i);
            break;
        }
        i++;
    }
}

void Action::removeArtClass(const QString &artefact_class)
{
    if (m_artefacts_class.contains(artefact_class))
    {
        m_artefacts_class.removeAt(m_artefacts_class.indexOf(artefact_class));
    }
}

bool Action::hasPrecondition(const QString& prec)
{
	bool exist = false;
	for (int i = 0; i < m_Precondition.size(); i++)
	{
		if (m_Precondition[i].getFactName() == prec)
		{
			exist = true;
			break;
		}
	}
	return exist;
}


bool Action::hasEffect(const QString& effect)
{
	bool exist = false;
	for (int i = 0; i < m_Effect.size(); i++)
	{
		if (m_Effect[i].getFactName() == effect)
		{
			exist = true;
			break;
		}
	}
	return exist;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

QDomElement Action::toXML(QDomDocument &doc)
{
    QDomElement ele = doc.createElement("action");
    ele.setAttribute("actionName", m_Name);
    ele.setAttribute("actionType", m_type);
    ele.setAttribute("executionTime", m_exec_time);
	ele.setAttribute("maxExeTime", m_exec_time_max);
	ele.setAttribute("minExeTime", m_exec_time_min);
    ele.setAttribute("exeType", m_execution_type);
	if (m_execution_type == Action::ExeType_OnTick ||m_execution_type == Action::ExeType_OnWake)
	{
		ele.setAttribute("exeParam", m_ID_actor_target);
	}
    QDomElement artefacts = doc.createElement("artefacts");
    for (int i = 0; i < m_artefacts_class.size(); i++)
    {
        QDomElement artefact = doc.createElement("artefactClass");
        artefact.appendChild(doc.createTextNode(m_artefacts_class[i]));
        artefacts.appendChild(artefact);
    }
    ele.appendChild(artefacts);
    QDomElement prec = doc.createElement("precondition");
    for (int i = 0; i < m_Precondition.size(); i++)
    {
        prec.appendChild(m_Precondition[i].toXML(doc));
    }
    ele.appendChild(prec);
    QDomElement effect = doc.createElement("effect");
    for (int i = 0; i < m_Effect.size(); i++)
    {
        effect.appendChild(m_Effect[i].toXML(doc));
    }
    ele.appendChild(effect);
    return ele;
}

void Action::fromXML(QDomElement ele)//, const QMap<QString, Artefact*>& artefact_map)
{
    setName(ele.attribute("actionName",""));
    setExeTime(ele.attribute("executionTime","").toInt());
	setMaxExeTime(ele.attribute("maxExeTime","").toInt());
	setMinExeTime(ele.attribute("minExeTime","").toInt());
    setType(ele.attribute("actionType","").toInt());
    QString exeType = ele.attribute("exeType","");
    if (!exeType.isEmpty())
    {
        setActionExeType((Action::ActionExeType)exeType.toInt());
    }
    else
    {
        setActionExeType(Action::ExeType_OneShot);
    }
	if (m_execution_type == Action::ExeType_OnTick ||m_execution_type == Action::ExeType_OnWake)
	{
		m_ID_actor_target = ele.attribute("exeParam", "");
	}
    QDomNode n = ele.firstChild();
    while (!n.isNull())
    {
        QDomElement e = n.toElement();
        if (e.tagName() == "precondition")
        {
            QDomNode fact = e.firstChild();
            while (!fact.isNull())
            {
                Fact f;
                f.fromXML(fact.toElement());
                addPrecondition(f);
                fact = fact.nextSibling();
            }
        }
        else if (e.tagName() == "effect")
        {
            QDomNode fact = e.firstChild();
            while (!fact.isNull())
            {
                Fact f;
                f.fromXML(fact.toElement());
                addEffect(f);
                fact = fact.nextSibling();
            }
        }
        if (e.tagName() == "artefacts")
        {
            QDomNode artefacts = e.firstChild();
            while (!artefacts.isNull())
            {
                QDomElement ele = artefacts.toElement();
                addArtefactClass(ele.text());
                artefacts = artefacts.nextSibling();
            }
        }
        n = n.nextSibling();
    }
}

//-----------------------------------------------------

QByteArray Action::toByteArray()
{
	QByteArray byte_array;
	QDataStream data(&byte_array, QIODevice::WriteOnly);
	data<<m_Name;
	data<<m_exec_time;
	data<<m_type;
	if (m_type == 1)
	{
		data<<m_ID_actor_origin;
		data<<m_ID_actor_target;
		data<<m_dialog_id;
	}
	return byte_array;
}

//-----------------------------------------------------

void Action::fromByteArray(QByteArray& byte_array)
{
	QDataStream data(&byte_array, QIODevice::ReadOnly);
	data>>m_Name;
	data>>m_exec_time;
	data>>m_type;
	if (m_type == 1)
	{
		data>>m_ID_actor_origin;
		data>>m_ID_actor_target;
		data>>m_dialog_id;
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void Action::setName( const QString& S )
{
    m_Name = S;
}
//-----------------------------------------------------------
void Action::setExeTime( const int exe_time )
{
    m_exec_time = exe_time;
}
//-----------------------------------------------------------
void Action::setMaxExeTime(const int time)
{
    m_exec_time_max = time;
}
//-----------------------------------------------------------
void Action::setMinExeTime(const int time)
{
    m_exec_time_min = time;
}

//-----------------------------------------------------------
void Action::setState( const int state )
{
    m_state = state;
}
//-----------------------------------------------------------
void Action::setType(const int type)
{
    m_type = type;
}
//-----------------------------------------------------------
void Action::setActionExeType(const ActionExeType type)
{
	m_execution_type = type;
}
//----------------------------------------------------------
void Action::setExclusive(const bool status)
{
	m_exclusive = status;
}
//-----------------------------------------------------------
QString Action::getName() const
{
    return m_Name;
}
//-----------------------------------------------------------
int Action::getExeTime() const
{
    return m_exec_time;
}
//-----------------------------------------------------------
int Action::getMaxExeTime() const
{
    return m_exec_time_max;
}
//-----------------------------------------------------------
int Action::getMinExeTime() const
{
    return m_exec_time_min;
}
//-----------------------------------------------------------
int Action::getState() const
{
    return m_state;
}
//-----------------------------------------------------------
int Action::getType() const
{
    return m_type;
}
//-----------------------------------------------------------
bool Action::isExclusive() const
{
	return m_exclusive;
}
//-----------------------------------------------------------
int Action::getActionExeType() const
{
	return m_execution_type;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////

QList<Fact> Action::getPreconditions() const
{
    return m_Precondition;
}
//------------------------------------------------
QList<Fact> Action::getEffect() const
{
    return m_Effect;
}
//------------------------------------------------
QList<QString> Action::getArtefactsClass() const
{
    return m_artefacts_class;
}

//------------------------------------------------
QString Action::getID_target() const
{
    return m_ID_actor_target;
}
//------------------------------------------------
QString Action::getID_origine() const
{
    return m_ID_actor_origin;
}
//-----------------------------------------------
QString Action::getDialogID() const
{
    return m_dialog_id;
}
//-----------------------------------------------
bool Action::isMandatoty() const
{
    return m_mandatory;
}
//----------------------------------------------
int Action::getNbAttempts() const
{
    return m_attempts_number;
}
//-----------------------------------------------
//Message * Action::getMessage()
//{
//    return &m_message;
//}
//---------------------------------------------
void Action::setID_target ( const QString& ID )
{
    m_ID_actor_target = ID;
}
//---------------------------------------------
void Action::setID_origine( const QString& ID )
{
    m_ID_actor_origin = ID;
}
//---------------------------------------------

void Action::setDialogID(const QString &id)
{
    m_dialog_id = id;
}

//---------------------------------------------

void Action::setMessage   ( const Message& message )
{
    m_message = message;
}

//-----------------------------------------------

void Action::setMandatory(const bool man)
{
    m_mandatory = man;
}

//--------------------------------------------

void Action::setNbAttempts(const int nb_attempts)
{
    m_attempts_number = nb_attempts;
}

//---------------------------------------------

Action& Action::operator=(const Action& a)
{
	m_Name = a.m_Name;
    m_Precondition = a.m_Precondition;
    m_Effect = a.m_Effect;
    m_exec_time = a.m_exec_time;
    m_exec_time_max = a.m_exec_time_max;
    m_exec_time_min = a.m_exec_time_min;
    m_type = a.m_type;
    m_ID_actor_origin = a.m_ID_actor_origin;
    m_ID_actor_target = a.m_ID_actor_target;
    m_message = a.m_message;
    m_state = a.getState();
    m_dialog_id = a.m_dialog_id;
	m_exclusive = a.m_exclusive;
	m_execution_type = a.m_execution_type;
    m_artefacts_class = a.m_artefacts_class;
    m_exec_time_max = a.m_exec_time_max;
    m_exec_time_min = a.m_exec_time_min;
    m_mandatory = a.m_mandatory;
    m_attempts_number = a.m_attempts_number;
	return *this;
}


}
